對於請求的處理如果都寫在路由器內那就太擠了,再 Laravel 中判定路由後都會將請求傳遞到控制器進行對應。
可以用指令建立控制器
sail artisan make:controller <ContorllerName>
建立好的控制器預設放在 App\Http\Controllers 資料夾中,並且 namespace 也是。
建好的空控制器
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
//
}
在這當中定義處理函式,跟前面路由器的 Callback 定義方式相同,可以帶上依賴注入的 Requeset 實例跟路徑參數,或是跟 Model 進行綁定
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Models\Photo $photo
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Photo $photo)
{
//
}
}
在路由器中引入控制器,並指定控制器中的方法給指定路由
// api.php
use App\Http\Controllers\UserController;
Route::get('/user/{id}', [UserController::class, 'show']);
可以在路由器中加上 Middleware
Route::get('profile', [UserController::class, 'show'])->middleware('auth');
也可以加在控制器中,這樣經由這個控制器處理的請求都會先經過 Middleware 處理
class UserController extends Controller
{
/**
* Instantiate a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log')->only('index');
$this->middleware('subscribed')->except('store');
}
}
通常一個控制器都是針對某一個 Model 進行處理,像是 UserController 負責處理 User 的 CRUD ,而因為對各 Model 的這類處理都大同小異, Laravel 就預設了快捷的 API 的定義方式
//web.php
Route::resource('photos', PhotoController::class);
Route::resource 當中包含了一組完整的CRUD 路由定義,而每個路由對應到控制器中的方法名稱也都指定好了,對照表如下:
請求方法 | 路由 | 控制器函式 | 路由名稱標籤 |
---|---|---|---|
GET | /photos | index | photos.index |
GET | /photos/create | create | photos.create |
POST | /photos | store | photos.store |
GET | /photos/{photo} | show | photos.show |
GET | /photos/{photo}/edit | edit | photos.edit |
PUT/PATCH | /photos/{photo} | update | photos.update |
DELETE | /photos/{photo} | destroy | photos.destroy |
{photo} 的部分通常是帶入主鍵 Id 的值,用來查詢單筆資料,對應的方法也都是用來處理單筆資料的。
Route::resource 主要是用來處理瀏覽器端(web.php)的請求,所以會包含要求建立/編輯表單畫面的 create/edit 路由。
而像是手機 App 來的請求不會用到 create/edit ,因為 App 都內建畫面了,所以也有另外的方法對應這方面的 api
// api.php
use App\Http\Controllers\PhotoController;
Route::apiResource('photos', PhotoController::class);
如上所述, apiResource 跟 resource 路由相比只是少了 create/edit 方法。
如果 resource 中有不需要的路由或是只需要其中幾個路由,可以再加定義
use App\Http\Controllers\PhotoController;
// 剔除不需要的路由
Route::resource('photos', PhotoController::class)->except([
'create', 'store', 'update', 'destroy'
]);
// 只取需要的路由
Route::resource('photos', PhotoController::class)->only([
'index', 'show'
]);
Laravel 提供了快捷的指令產生可以對應 resource 路由的控制器
sail artisan make:controller PhotoController --resource
這樣生成的控制器中會先生成 index/create 等對應 Route::resource 的空函式,也會定義好預設的參數,以 show 為例
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
會先定義好路徑參數為 $id。
如果想略過用 $id 查詢資料的步驟,可以直接建立與 Model 連結的控制器
sail artisan make:controller PhotoController --resource --model=Photo
指定了 Model 的話,參數會直接變成該 Model 的型別,根據上一篇路由綁定 Model 的說明,就可以直接取出該 id 對應的資料進行處理
/**
* Display the specified resource.
*
* @param \App\Models\Photo $photo
* @return \Illuminate\Http\Response
*/
public function show(Photo $photo)
{
//
}
產生對應 apiResource 的控制器,只是少了 create/edit 方法,其他都跟 resource 指令的結果相同
sail artisan make:controller PhotoController --api